using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace PS.Practices.SiteBuilder.Features.Schema
{
    class Prepocessor
    {
        /// <summary>
        /// Preprocess file and returns path to newly creates preprocessed file
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns>path to preprocessed file</returns>
        public string Run(string filePath)
        {
            if(!File.Exists(filePath))
            {
                throw new FileNotFoundException("xml document not found", filePath);
            }
            
            return SaveToTempFile(ProcessIncludes(ReadTextFile(filePath)));
        }

        private string ReadTextFile(string filePath)
        {
            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// Returns path to created temp file
        /// </summary>
        /// <returns>file path</returns>
        private string SaveToTempFile(string content)
        {
            string tempFile = Path.GetTempFileName();
            using(FileStream fs = 
                new FileStream(tempFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
            {
                using(StreamWriter sw = new StreamWriter(fs))
                {
                    sw.Write(content);
                }
            }
            return tempFile;
        }

        public string ProcessIncludes(string content)
        {
            Regex r = new Regex(@"<\?include\s+file=""(?<filePath>.+)""\?>");
            MatchCollection mc = r.Matches(content);
            StringBuilder sb = new StringBuilder(content);

            foreach (Match match in mc)
            {
                string includeFile = match.Groups["filePath"].Value;
                
                if(File.Exists(includeFile))
                {
                    string includeFileContent = ReadTextFile(includeFile);
                    sb.Replace(match.Value, includeFileContent);
                }
            }

            return sb.ToString();
        }
    }
}
